﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Windows.Forms;
using Newtonsoft.Json;

namespace WinServiceMonitor
{
    public partial class Form1 : Form
    {
        private string dotNetFullPath = @"C:\Program Files\dotnet\dotnet.exe";
        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
            this.btnInstall.Click += BtnInstall_Click;
            this.btnUninstall.Click += BtnUninstall_Click;
            this.btnStart.Click += BtnStart_Click;
            this.btnStop.Click += BtnStop_Click;
            this.btnRestart.Click += BtnRestart_Click;
            this.FormClosing += Form1_FormClosing;
            this.btnAllRestart.Click += BtnAllRestart_Click;
            this.btnAllStart.Click += BtnAllStart_Click;
            this.btnAllStop.Click += BtnAllStop_Click;
            this.btnAllUnstall.Click += BtnAllUnstall_Click;
        }


        private void Form1_Load(object sender, EventArgs e)
        {
            RefWindowsServices();
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult result = MessageBox.Show("你确定要退出程序吗?", "操作提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
            if (result == DialogResult.OK)
            {
                System.Environment.Exit(0);
            }
            else
            {
                e.Cancel = true;
            }
        }
        /// <summary>
        /// 卸载服务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnUninstall_Click(object sender, EventArgs e)
        {
            if (this.listView1.FocusedItem == null || this.listView1.FocusedItem.Tag == null)
            {
                return;
            }
            var service = this.listView1.FocusedItem.Tag as ServiceController;
            UnstallService(service);
            RefWindowsServices();
        }

        private void UnstallService(ServiceController service)
        {
            List<string> cmdArray = new List<string>();
            var cmd = $@"nssm stop {service.ServiceName}";
            //::执行安装服务指令5008
            cmdArray.Add(cmd);
            //::应用程序配置Tab
            cmd = $@"nssm remove {service.ServiceName}";
            cmdArray.Add(cmd);
            ExcuteDosCommand(cmdArray);
        }

        private void BtnStop_Click(object sender, EventArgs e)
        {
            if (this.listView1.FocusedItem == null || this.listView1.FocusedItem.Tag == null)
            {
                return;
            }
            var service = this.listView1.FocusedItem.Tag as ServiceController;
            StopService(service);
            RefWindowsServices();
        }

        private void StopService(ServiceController service)
        {
            List<string> cmdArray = new List<string>();
            var cmd = $@"nssm stop {service.ServiceName}";
            //::执行安装服务指令5008
            cmdArray.Add(cmd);
            //::应用程序配置Tab
            cmd = $@"nssm status {service.ServiceName}";
            cmdArray.Add(cmd);
            ExcuteDosCommand(cmdArray);
        }

        private void BtnStart_Click(object sender, EventArgs e)
        {
            if (this.listView1.FocusedItem == null || this.listView1.FocusedItem.Tag == null)
            {
                return;
            }
            var service = this.listView1.FocusedItem.Tag as ServiceController;
            StartService(service);
            RefWindowsServices();
        }

        private void StartService(ServiceController service)
        {
            List<string> cmdArray = new List<string>();
            var cmd = $@"nssm start {service.ServiceName}";
            //::执行安装服务指令5008
            cmdArray.Add(cmd);
            //::应用程序配置Tab
            cmd = $@"nssm status {service.ServiceName}";
            cmdArray.Add(cmd);
            ExcuteDosCommand(cmdArray);
        }

        private void BtnRestart_Click(object sender, EventArgs e)
        {
            if (this.listView1.FocusedItem == null || this.listView1.FocusedItem.Tag == null)
            {
                return;
            }
            var service = this.listView1.FocusedItem.Tag as ServiceController;
            RestartService(service);
            RefWindowsServices();
        }

        private void RestartService(ServiceController service)
        {
            List<string> cmdArray = new List<string>();
            var cmd = $@"nssm restart {service.ServiceName}";
            //::执行安装服务指令5008
            cmdArray.Add(cmd);
            //::应用程序配置Tab
            cmd = $@"nssm status {service.ServiceName}";
            cmdArray.Add(cmd);
            ExcuteDosCommand(cmdArray);
        }

        /// <summary>
        /// 安装服务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnInstall_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(this.textBox1.Text))
            {
                MessageBox.Show("请输入.net core发布程序路径，可输入上级目录，批量打包服务");
                return;
            }
            List<string> list = new List<string>();
            Director(this.textBox1.Text.TrimEnd('\\'), list);
            foreach (var folder in list)
            {
                string logDic = folder.TrimEnd('\\') + @"\WinSerLogs";
                string infoLog = logDic + @"\Info.log";
                string errorLog = logDic + @"\Error.log";
                if (!Directory.Exists(logDic))
                {
                    Directory.CreateDirectory(logDic);
                }
                if (!File.Exists(infoLog))
                {
                    File.Create(infoLog);
                }
                if (!File.Exists(errorLog))
                {
                    File.Create(errorLog);
                }
                #region 解析dll名称
                var dllName = "";
                using (StreamReader sr = new StreamReader(folder.TrimEnd('\\') + "\\web.config"))
                {
                    var content = sr.ReadToEndAsync().Result;
                    dllName = StringMid(content, @"arguments="".\", @"""");
                }
                if (string.IsNullOrEmpty(dllName))
                {
                    Log("web.config中未获取到dll名称");
                    return;
                }
                #endregion
                #region 解析服务信息
                JsonModel windowsServiceModel = null;
                using (StreamReader sr = new StreamReader(folder.TrimEnd('\\') + "\\appsettings.json"))
                {
                    var jsonStr = sr.ReadToEndAsync().Result;
                    windowsServiceModel = JsonConvert.DeserializeObject<JsonModel>(jsonStr);
                }

                if (windowsServiceModel == null || windowsServiceModel.WindowsService == null)
                {
                    Log("appsettings.json中未获取到WindowsService节点");
                    return;
                }
                #endregion
                InstallService(windowsServiceModel.WindowsService, dllName, folder);
            }
        }

        private void BtnAllUnstall_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listView1.Items)
            {
                UnstallService(item.Tag as ServiceController);
            }
            RefWindowsServices();
        }

        private void BtnAllStop_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listView1.Items)
            {
                StopService(item.Tag as ServiceController);
            }
            RefWindowsServices();
        }

        private void BtnAllStart_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listView1.Items)
            {
                StartService(item.Tag as ServiceController);
            }
            RefWindowsServices();
        }

        private void BtnAllRestart_Click(object sender, EventArgs e)
        {
            foreach (ListViewItem item in this.listView1.Items)
            {
                RestartService(item.Tag as ServiceController);
            }
            RefWindowsServices();
        }

        /// <summary>
        /// 安装服务
        /// </summary>
        /// <param name="ws"></param>
        /// <param name="dllName"></param>
        /// <param name="folder"></param>
        private void InstallService(WindowsService ws, string dllName, string folder)
        {
            List<string> cmdArray = new List<string>();
            var cmd = $@"nssm install {ws.ServiceName} ""{dotNetFullPath}""";
            //::执行安装服务指令5008
            cmdArray.Add(cmd);
            //::应用程序配置Tab
            cmd = $@"nssm set {ws.ServiceName} Application ""{dotNetFullPath}""";
            cmdArray.Add(cmd);
            cmd = $@"nssm set {ws.ServiceName} AppDirectory ""{folder}""";
            cmdArray.Add(cmd);
            cmd = $@"nssm set {ws.ServiceName} AppParameters ""{dllName}"" --urls={ws.Urls}";
            cmdArray.Add(cmd);
            //::监控日志
            cmd = $@"nssm set {ws.ServiceName} AppStdout {folder.TrimEnd('\\')}\WinSerLogs\Info.log";
            cmdArray.Add(cmd);
            cmd = $@"nssm set {ws.ServiceName} AppStderr {folder.TrimEnd('\\')}\WinSerLogs\Error.log";
            cmdArray.Add(cmd);
            //::详情Tab（例如：服务的描述信息）
            cmd = $@"nssm set {ws.ServiceName} DisplayName {ws.ServiceName}";
            cmdArray.Add(cmd);
            cmd = $@"nssm set {ws.ServiceName} Description {ws.Description}";
            cmdArray.Add(cmd);
            cmd = $@"nssm set {ws.ServiceName} Start SERVICE_AUTO_START";
            cmdArray.Add(cmd);
            //::安装完成后，启动前的服务状态
            cmd = $@"nssm status {ws.ServiceName}";
            cmdArray.Add(cmd);
            cmd = $@"nssm start {ws.ServiceName}";
            cmdArray.Add(cmd);
            //::启动服务后的服务状态
            cmd = $@"nssm status {ws.ServiceName}";
            cmdArray.Add(cmd);
            ExcuteDosCommand(cmdArray);
        }
        /// <summary>
        /// 递归目录
        /// </summary>
        /// <param name="dir"></param>
        /// <param name="list"></param>
        public void Director(string dir, List<string> list)
        {
            try
            {
                DirectoryInfo d = new DirectoryInfo(dir);
                FileInfo[] files = d.GetFiles();//文件
                DirectoryInfo[] directs = d.GetDirectories();//文件夹
                foreach (FileInfo f in files)
                {
                    if (f.FullName.Contains("web.config"))
                    {
                        list.Add(d.FullName);
                        break;
                    }
                }
                //获取子文件夹内的文件列表，递归遍历  
                foreach (DirectoryInfo dd in directs)
                {
                    Director(dd.FullName, list);
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }
        /// <summary>
        /// 刷新服务列表
        /// </summary>
        private void RefWindowsServices()
        {
            this.listView1.Items.Clear();
            // 获取系统服务列表
            ServiceController[] services = ServiceController.GetServices();
            foreach (var ser in services.Where(t => t.ServiceName.Contains(this.textBox2.Text.Trim())))
            {
                ListViewItem lvi = new ListViewItem();
                lvi.Tag = ser;
                lvi.Text = ser.ServiceName;
                lvi.SubItems.Add(ser.DisplayName);
                lvi.SubItems.Add(ser.Status.ToString());
                this.listView1.Items.Add(lvi);
            }
        }
        public string StringMid(string Src, string Left, string Right)
        {
            string lRusult = string.Empty;
            if (Src != string.Empty)
            {
                int dwLeft = Src.IndexOf(Left);
                if (dwLeft != -1)
                {
                    dwLeft += Left.Length;
                    int dwRight = Src.IndexOf(Right, dwLeft);
                    if (dwRight != -1)
                    {
                        lRusult = Src.Substring(dwLeft, dwRight - dwLeft);
                    }
                }
            }
            return lRusult;
        }
        /// <summary>
        /// 执行cmd命令
        /// </summary>
        /// <param name="cmdArray"></param>
        private void ExcuteDosCommand(List<string> cmdArray)
        {
            try
            {
                Process p = new Process();
                p.StartInfo.FileName = "cmd";
                p.StartInfo.UseShellExecute = false;
                p.StartInfo.RedirectStandardInput = true;
                p.StartInfo.RedirectStandardOutput = true;
                p.StartInfo.RedirectStandardError = true;
                p.StartInfo.CreateNoWindow = false;
                p.OutputDataReceived += new DataReceivedEventHandler(sortProcess_OutputDataReceived);
                p.ErrorDataReceived += sortProcess_OutputDataReceived;
                p.Start();
                using (StreamWriter cmdWriter = p.StandardInput)
                {
                    p.BeginOutputReadLine();
                    p.BeginErrorReadLine();
                    foreach (var cmd in cmdArray)
                    {
                        p.StandardInput.WriteLine(cmd);
                    }
                }
                p.WaitForExit();
                p.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show("执行命令失败，请检查输入的命令是否正确！");
            }
        }

        private void sortProcess_OutputDataReceived(object sender, DataReceivedEventArgs e)
        {
            if (!String.IsNullOrEmpty(e.Data))
            {
                Log(e.Data);
            }
        }

        public void Log(string log)
        {
            this.BeginInvoke(new Action(
                () => { this.richTextBox1.AppendText(log + Environment.NewLine); }
            ));
        }
        private void button2_Click(object sender, EventArgs e)
        {
            RefWindowsServices();
        }
    }

    public class JsonModel
    {
        public WindowsService WindowsService { get; set; }
    }
    public class WindowsService
    {
        public string ServiceName { get; set; }
        public string DisplayName { get; set; }
        public string Description { get; set; }
        public string Urls { get; set; }
    }
}
